﻿using System;
using System.Collections.Generic;
using System.Text;
using Tsanie.DmPoster.Models;
using Tsanie.DmPoster.Event;

namespace Tsanie.DmPoster.Utils {

    /// <summary>
    /// 弹幕管理器
    /// </summary>
    /// <typeparam name="TComment">弹幕类型</typeparam>
    public class CommentManager<TComment> where TComment : CommentBase {
        private PropertyHandler _propertyChanged;

        private LinkedList<TComment> _comments;

        public int Count { get { return _comments.Count; } }

        public TComment this[int index] {
            get {
                int count = _comments.Count;
                if (index < 0 || index >= count)
                    return null;
                TComment rtn = null;
                if (index < count / 2) {
                    LinkedListNode<TComment> first = _comments.First;
                    for (int i = 0; i < index; i++) {
                        first = first.Next;
                    }
                    rtn = first.Value;
                } else {
                    LinkedListNode<TComment> last = _comments.Last;
                    for (int i = 1; i < count - index; i++) {
                        last = last.Previous;
                    }
                    rtn = last.Value;
                }
                return rtn;
            }
        }
        public TComment this[string idkey] {
            get {
                TComment comm = null;
                int id = int.Parse(idkey);
                LinkedListNode<TComment> first = _comments.First;
                while (first != null) {
                    if (first.Value.Id == id) {
                        comm = first.Value;
                        break;
                    }
                    first = first.Next;
                }
                return comm;
            }
        }

        public CommentManager(PropertyHandler handler) {
            _comments = new LinkedList<TComment>();
            _propertyChanged = handler;
        }

        public bool Contains(TComment comm) {
            return _comments.Contains(comm);
        }
        public void Add(TComment comm) {
            comm._propertyChanged = _propertyChanged;
            // 按顺序插入
            LinkedListNode<TComment> add = new LinkedListNode<TComment>(comm);
            if (this.Count == 0) {
                _comments.AddFirst(comm);
                return;
            }
            LinkedListNode<TComment> node = _comments.First;
            while (node != null) {
                if (CommentBase.Compare(node.Value, comm) > 0) {
                    // 大于，插入到前面
                    _comments.AddBefore(node, comm);
                    return;
                }
                node = node.Next;
            }
            // 插入尾端
            _comments.AddLast(comm);
        }
        public void AddBack(TComment comm) {
            comm._propertyChanged = _propertyChanged;
            // 按顺序从底部插入
            LinkedListNode<TComment> add = new LinkedListNode<TComment>(comm);
            if (this.Count == 0) {
                _comments.AddLast(comm);
                return;
            }
            LinkedListNode<TComment> node = _comments.Last;
            while (node != null) {
                if (CommentBase.Compare(node.Value, comm) < 0) {
                    // 小于，插入到后面
                    _comments.AddAfter(node, comm);
                    return;
                }
                node = node.Previous;
            }
            // 插入头部
            _comments.AddFirst(comm);
        }
        public bool Remove(TComment comm) {
            return _comments.Remove(comm);
        }
        public bool Remove(int index) {
            return this.Remove(this[index]);
        }
        public bool Remove(string idkey) {
            int id = int.Parse(idkey);
            LinkedListNode<TComment> first = _comments.First;
            while (first != null) {
                if (first.Value.Id == id) {
                    _comments.Remove(first);
                    return true;
                }
                first = first.Next;
            }
            return false;
        }
        public void Clear() {
            _comments.Clear();
        }

        public void Order(TComment comm) {
            if (_comments.Remove(comm))
                this.Add(comm);
        }
        public void ForEach(Predicate<TComment> exec) {
            LinkedListNode<TComment> node = _comments.First;
            while (node != null) {
                if (!exec(node.Value))
                    break;
                node = node.Next;
            }
        }
        public TComment[] Copy() {
            TComment[] comms = new TComment[this.Count];
            LinkedListNode<TComment> node = _comments.First;
            int index = 0;
            while (node != null) {
                comms[index++] = node.Value;
                node = node.Next;
            }
            return comms;
        }
    }
}
